package serviceImp;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.springframework.stereotype.Service;

import service.MyService;
import util.SpringContextUtil;
@Service
public class MyServiceImp implements MyService{

	public MyServiceImp() {
		System.out.println(this.getClass().getName());
	}

	@Override
    public Object callApp(String serviceName,String methodName,Object[] parameterValues,Class<?>[] parameterTypes) {
        Object obj = SpringContextUtil.getBean(serviceName);
        Class<?> classType = obj.getClass();
        try {
            if(parameterValues == null || parameterValues.length <= 0){
                Method method = classType.getMethod(methodName);
                return method.invoke(obj);
            }else{
                Method method = classType.getMethod(methodName, parameterTypes);
                return method.invoke(obj, parameterValues);
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    /***
     * 远程调用,不需要带参数类型
     */
    public Object callApp(String serviceName,String methodName,Object[] parameterValues){
        Object obj = SpringContextUtil.getBean(serviceName);
        Class<?> classType = obj.getClass();
        try {
            //参数类型的解析
            Method method = null;
            if(parameterValues == null || parameterValues.length <= 0){
                method = classType.getMethod(methodName);
                return method.invoke(obj);
            }else if(parameterValues != null && parameterValues.length > 0){
                Class<?>[] parameterTypes = null;
                parameterTypes = new Class<?>[parameterValues.length];
                for(int i = 0; i < parameterValues.length ;i++){
                    if(parameterValues[i] == null){//存在参数为空,无法获取参数类型
                        parameterTypes = null;
                        break;
                    }
                    parameterTypes[i] = parameterValues[i].getClass();
                }
                //参数与类型匹配时调用
                if(parameterTypes != null && parameterTypes.length == parameterValues.length){
                    method = classType.getMethod(methodName, parameterTypes);
                    return method.invoke(obj, parameterValues);
                }else{//传入的参数存在null，无法获取参数类型
                    Method[] methodList = classType.getMethods();
                    for(Method md : methodList){
                        if(methodName.equals(md.getName())){
                            parameterTypes = md.getParameterTypes();
                            //XXX 验证待完善，需验证参数类型
                            if(parameterTypes != null && parameterTypes.length == parameterValues.length){
                                method = md;
                                break;
                            }
                        }
                    }
                    if(method != null){
                        return method.invoke(obj, parameterValues);
                    }else{
                        throw new NoSuchMethodException("找不到对应的服务方法,请核查！[服务名称:"+serviceName+"][方法名称:"+methodName+"]");
                    }
                }
            }
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 远程调用，无参数
     */
    public Object callApp(String serviceName,String methodName){
        return callApp(serviceName,methodName,null);
    }
}
